/*
 * Copyright (c) Huawei Device Co., Ltd. 2023. All rights reserved.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#ifndef SERVICE_IMPL_H
#define SERVICE_IMPL_H

#include <map>
#include <mutex>

#include "service_stub.h"

namespace OHOS {
namespace SE {
class ServiceManager;
class SecureElementAgent;
using SeNameAndAgentMap = std::pair<std::string, std::shared_ptr<SecureElementAgent>>;

class ServiceImpl final : public OMAPI::ServiceStub, public std::enable_shared_from_this<ServiceImpl> {
public:
    /**
     * @brief Constructor of ServiceImpl
     * @param service The service manager for this sa.
     * @param table The name and the agent mapping for all secure element.
     */
    explicit ServiceImpl(std::weak_ptr<ServiceManager> service, std::vector<SeNameAndAgentMap>& table);

    ~ServiceImpl() override;

    /**
     * @brief Get the list of available SE reader names. There must be no duplicated names in the returned list.
     * @param readerList The reader names existed.
     * @return The status code for function calling.
     */
    ErrorCode GetReaders(std::vector<std::string> &readerList) override;
    /**
     * @brief Get the reader instance by the name.
     * @param readerName The reader name
     * @param iface The Reader interface object, used for IPC.
     * @return The status code for function calling.
     */
    ErrorCode GetReaderInterface(const std::string &readerName, sptr<OMAPI::ISecureElementReader> &iface) override;
    /**
     * @brief Checks if the application defined by the bundle name is authorized
     * to receive the NFC transaction events for the defined AID.
     * @param readerName The reader name
     * @param aid The SE application ID
     * @param bundleNames The all bundle names to check.
     * @param allowedStatus The checking status for all bundle names, true or false for each one.
     * @return The status code for function calling.
     */
    ErrorCode IsNfcEventAllowed(const std::string &readerName, const std::string &aid,
        std::vector<std::string> bundleNames, std::vector<bool> &allowedStatus) override;

    /**
     * @brief Shutdown the se_service process if no client bound to service
     * @param callingUniqueTag who call the service
     * @return The status code for function calling.
     */
    ErrorCode Shutdown() override;

    /**
     * @brief RegisterCallerListener se_service process
     * @param obj The remote object of service.
     * @return The status code for function calling.
     */
    ErrorCode RegisterCallerListener(const sptr<IRemoteObject> &obj) override;

    void OnRemoteDied(const std::string &callingUniqueTag);

private:
    // check Only one listener can be registered for the same callingUniqueTag.
    bool IsRegisterAppListener(const std::string &callingUniqueTag);
    // Unload SA
    static void UnloadSESA();
private:
    // inner class used to monitor the caller application state
    class CallerApplicationDeathReceiver;

    // death receiver for all caller applications.
    // key: string(called tokenID) + string(called PID)
    std::map<std::string, sptr<CallerApplicationDeathReceiver>> applicationListeners_;

    // the sa manager.
    std::weak_ptr<ServiceManager> serviceManager_;

    // all secure elements found by this service, eSE and SIM.
    std::vector<SeNameAndAgentMap>& secureElementAgents_;

    // mutext lock for service.
    std::mutex mutex_{};

    std::string callingUniqueTag_;

    static uint32_t unloadSaTimerId;
};
}  // namespace SE
}  // namespace OHOS
#endif // !SERVICE_IMPL_H
